%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Module summary
%%
%% Main authors: 
%% Progress to usefulness: 
%%
%%%%%%%%%%%%%%%%%%%%%%%

-module(chord_worker).
-behaviour(gen_server).
-include("db.hrl").

-export([start_link/0,start_link/1]).
-export([init/1, handle_call/3,handle_cast/2,handle_info/2
        ,code_change/3,terminate/2]).

-import(chord_lib, [dbg_str/2, dbg_format/3, dbg_header/2]).
-import(chord_lib, [dbg_msg/2, dbg_msg_loc/2]).
-import(chord_lib, [get_node/1, get_pid/1, get_position/1]).
-import(chord_lib, [get_finger/2, set_finger/3, finger_start/2, get_M/0, modspace/1]).

start_link() ->
    %io:format("Starting Chord Worker\n"),
    gen_server:start_link(?MODULE,[],[]).

start_link(Args) ->
    %io:format("Starting Chord Worker\n"),
    gen_server:start_link(?MODULE,Args,[]).

init(State) ->
    {ok, State}.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Actions to be called from the upper layers
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

handle_cast({call, {lookup, Key}, From}, State) ->
        dbg_msg("lookup", State),
        LookupModule = State#chord.lookup,
        LookupModule:lookup_call(Key, From, State),
        %% Let the backend module handle how a reply is sent to the caller
        {stop, normal, State};

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Actions to be called from other Chord nodes
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

handle_cast({call, {get_successor}, From}, State) ->
        dbg_msg("get_successor", State),
        Suc = get_finger(1, State),
        gen_server:reply(From, Suc),
        {stop, normal, State};

handle_cast({call, {get_predecessor}, From}, State) ->
        dbg_msg("get_predecessor", State),
        Pred = State#chord.predecessor,
        gen_server:reply(From, Pred),
        {stop, normal, State};

handle_cast({call, {find_successor, Id}, From}, State) ->
        dbg_msg("find_successor", State),
        LookupModule = State#chord.lookup,
        LookupModule:find_successor_call(Id, From, State),
        %% Let the backend module handle how a reply is sent to the caller
        {stop, normal, State};

handle_cast({call, {find_predecessor, Id}, From}, State) ->
        dbg_msg("find_predecessor", State),
        LookupModule = State#chord.lookup,
        LookupModule:find_predecessor_call(Id, From, State),
        %% Let the backend module handle how a reply is sent to the caller
        {stop, normal, State};

handle_cast({call, {closest_preceding_finger, Id}, From}, State) ->
        dbg_msg("closest_preceding_finger", State),
        Fin = chord_lib:closest_preceding_finger(Id, State),
        gen_server:reply(From, Fin),
        {stop, normal, State};

handle_cast({cast, {lookup_cast, Hash, From}}, State) ->
    dbg_msg("lookup_cast", State),
    chord_distributed:lookup_cast(Hash, From, State),
    %% Let the backend module handle how a reply is sent to the caller.
    %% The reply may even be sent from another node. 
    {stop, normal, State};

handle_cast({cast, {find_successor_cast, Hash, From}}, State) ->
    dbg_msg("find_successor_cast", State),
    chord_distributed:find_successor_cast(Hash, From, State),
    %% Let the backend module handle how a reply is sent to the caller.
    %% The reply may even be sent from another node. 
    {stop, normal, State};

handle_cast({cast, {find_predecessor_cast, Hash, From}}, State) ->
    dbg_msg("find_predecessor_cast", State),
    chord_distributed:find_predecessor_cast(Hash, From, State),
    %% Let the backend module handle how a reply is sent to the caller.
    %% The reply may even be sent from another node. 
    {stop, normal, State};

handle_cast(_Msg, State) ->
    {stop, normal, State}.

handle_call(_Msg, _From, State) ->
    {noreply, State}.

% Function called when terminated
terminate(normal,_State) ->
    ok;
terminate(_Reason,_State) ->
    io:format("Terminating Chord worker~n").

handle_info(Info, State) ->
    io:format("Received info message: ~w~n", Info),
    {noreply ,State}.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

